package models;

import jodd.bean.BeanCopy;
import models.admin.AdminDept;
import models.admin.AdminUser;
import models.constants.AvailableStatus;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import play.db.jpa.JPA;
import play.db.jpa.Model;
import util.common.ClassUtil;
import util.common.ConvertUtil;
import util.common.DateUtil;

import javax.persistence.*;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by liming on 2016/1/31.
 */
@MappedSuperclass
public class BaseModel extends Model {

    /**
     * 保存方法
     *
     * @param <T>
     */
    public <T extends BaseModel> void update() {
        List eList = em().createQuery("select e from " + this.getClass().getName() + " e where e.id=" + this.id.toString()).getResultList();
        if (eList != null && eList.size() > 0) {
            T target = (T) eList.get(0);
            BeanCopy.beans(this, target).ignoreNulls(true).copy();
            target.save();
        }
    }

    public final static String SQL_CODE_SELECT = "select version,code_num,code_date,prefix,code_date_available from admin_business where main_entity = ?";
    public final static String SQL_CODE_UPDDATE = "update admin_business set code_num = ?,code_date=?,version=version+1 where main_entity = ? and version = ?";

    /**
     * 加载code
     */
    public void loadKey() {
        ClassUtil.setFiledValue(this, "code", loadCode(false));
    }

    /**
     * 使用乐观锁解决集群下分布式服务生成流水号重复问题
     *
     * @param isError
     * @return
     */
    private String loadCode(boolean isError) {
        String entityName = this.getClass().getSimpleName();
        Query query = null;
        if (isError)
            query = JPA.newEntityManager().createNativeQuery(SQL_CODE_SELECT).setParameter(1, entityName);
        else
            query = em().createNativeQuery(SQL_CODE_SELECT).setParameter(1, entityName);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String, Object>> businessList = query.getResultList();

        if (businessList == null || businessList.size() == 0)
            return "";

        Map<String, Object> adminBuisness = businessList.get(0);
        Integer version = ConvertUtil.toInteger(adminBuisness.get("version"));
        String prefix = ConvertUtil.toString(adminBuisness.get("prefix"));
        Integer codeNum = ConvertUtil.toInteger(adminBuisness.get("code_num"));
        String codeDateAvailable = ConvertUtil.toString(adminBuisness.get("code_date_available"));
        String orgDateStr = ConvertUtil.toString(adminBuisness.get("code_date"));
        String todayDataStr = "";

        if (codeDateAvailable.equals(AvailableStatus.AVAILABLE.toString())) {
            Date today = DateUtil.getBeginOfDay();
            todayDataStr = DateUtil.dateToString(today, "yyyyMMdd");

            if (!todayDataStr.equals(orgDateStr)) {
                codeNum = 0;
            }
        }

        Query updateQuery = em().createNativeQuery(SQL_CODE_UPDDATE)
                .setParameter(1, ++codeNum)
                .setParameter(2, todayDataStr)
                .setParameter(3, entityName)
                .setParameter(4, version);
        int updateQty = updateQuery.executeUpdate();
        if (updateQty > 0) {
            return prefix + todayDataStr + ConvertUtil.toString(10000 + codeNum).substring(1);
        } else {
            return loadCode(true);
        }

    }

    //创建部门
    @ManyToOne
    @JoinColumn(name = "ct_dept_id")
    public AdminDept ctDept;

    //创建日期
    @Column(name = "create_at")
    @Temporal(TemporalType.TIMESTAMP)
    public Date createAt;

    //创建人
    @ManyToOne
    @JoinColumn(name = "creator_id")
    public AdminUser creator;

    //最后修改日期
    @Column(name = "modify_at")
    @Temporal(TemporalType.TIMESTAMP)
    public Date modifyAt;

    //最后修改人
    @ManyToOne
    @JoinColumn(name = "modifier_id")
    public AdminUser modifier;

}
